home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / game / shoot / ADoomPPC_src.lha / ADoomPPC_src / d_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-18  |  31.3 KB  |  1,252 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //      DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
  21. //      plus functions to determine game mode (shareware, registered),
  22. //      parse command line parameters, configure game parameters (turbo),
  23. //      and call the startup functions.
  24. //
  25. //-----------------------------------------------------------------------------
  26.  
  27. #ifdef __VBCC__
  28. #define R_OK 0
  29. #endif
  30.  
  31. static const char rcsid[] = "$Id: d_main.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
  32.  
  33. #define BGCOLOR         7
  34. #define FGCOLOR         8
  35.  
  36.  
  37. #ifdef NORMALUNIX
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #ifndef __VBCC__
  41. #include <unistd.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #include <fcntl.h>
  45. #endif
  46. #endif
  47.  
  48.  
  49. #include "doomdef.h"
  50. #include "doomstat.h"
  51.  
  52. #include "dstrings.h"
  53. #include "sounds.h"
  54.  
  55.  
  56. #include "z_zone.h"
  57. #include "w_wad.h"
  58. #include "s_sound.h"
  59. #include "v_video.h"
  60.  
  61. #include "f_finale.h"
  62. #include "f_wipe.h"
  63.  
  64. #include "m_argv.h"
  65. #include "m_misc.h"
  66. #include "m_menu.h"
  67.  
  68. #include "i_system.h"
  69. #include "i_sound.h"
  70. #include "i_video.h"
  71.  
  72. #include "g_game.h"
  73.  
  74. #include "hu_stuff.h"
  75. #include "wi_stuff.h"
  76. #include "st_stuff.h"
  77. #include "am_map.h"
  78.  
  79. #include "p_setup.h"
  80. #include "r_local.h"
  81.  
  82. /* DeHacked Patch !!! */
  83. #include "dehacked.h"
  84.  
  85. #include "d_main.h"
  86.  
  87. //
  88. // D-DoomLoop()
  89. // Not a globally visible function,
  90. //  just included for source reference,
  91. //  called by D_DoomMain, never exits.
  92. // Manages timing and IO,
  93. //  calls all ?_Responder, ?_Ticker, and ?_Drawer,
  94. //  calls I_GetTime, I_StartFrame, and I_StartTic
  95. //
  96. void D_DoomLoop (void);
  97.  
  98.  
  99. char*           wadfiles[MAXWADFILES];
  100.  
  101.  
  102. boolean         devparm;        // started game with -devparm
  103. boolean         nomonsters;     // checkparm of -nomonsters
  104. boolean         respawnparm;    // checkparm of -respawn
  105. boolean         fastparm;       // checkparm of -fast
  106. boolean         rotatemap;      // checkparm of -rotatemap
  107. boolean         maponhu;        // checkparm of -maponhu
  108.  
  109. boolean         drone;
  110.  
  111. boolean         singletics = false; // debug flag to cancel adaptiveness
  112.  
  113.  
  114.  
  115. //extern int soundVolume;
  116. //extern  int   sfxVolume;
  117. //extern  int   musicVolume;
  118.  
  119. extern  boolean inhelpscreens;
  120. extern  boolean maponhu;
  121.  
  122. skill_t         startskill;
  123. int             startepisode;
  124. int             startmap;
  125. boolean         autostart;
  126.  
  127. FILE*           debugfile;
  128.  
  129. boolean         advancedemo;
  130.  
  131.  
  132.  
  133.  
  134. char            wadfile[1024];          // primary wad file
  135. char            mapdir[1024];           // directory of development maps
  136. char            basedefault[1024];      // default file
  137.  
  138.  
  139. void D_CheckNetGame (void);
  140. void D_ProcessEvents (void);
  141. void G_BuildTiccmd (ticcmd_t* cmd);
  142. void D_DoAdvanceDemo (void);
  143.  
  144.  
  145. //
  146. // EVENT HANDLING
  147. //
  148. // Events are asynchronous inputs generally generated by the game user.
  149. // Events can be discarded if no responder claims them
  150. //
  151. event_t         events[MAXEVENTS];
  152. int             eventhead;
  153. int             eventtail;
  154.  
  155.  
  156. //
  157. // D_PostEvent
  158. // Called by the I/O functions when input is detected
  159. //
  160. void D_PostEvent (event_t* ev)
  161. {
  162.     events[eventhead] = *ev;
  163.     eventhead = (++eventhead)&(MAXEVENTS-1);
  164. }
  165.  
  166.  
  167. //
  168. // D_ProcessEvents
  169. // Send all the events of the given timestamp down the responder chain
  170. //
  171. void D_ProcessEvents (void)
  172. {
  173.     event_t*    ev;
  174.         
  175.     // IF STORE DEMO, DO NOT ACCEPT INPUT
  176.     if ( ( gamemode == commercial )
  177.          && (W_CheckNumForName("map01")<0) )
  178.       return;
  179.         
  180.     for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) )
  181.     {
  182.         ev = &events[eventtail];
  183.         if (M_Responder (ev))
  184.             continue;               // menu ate the event
  185.         G_Responder (ev);
  186.     }
  187. }
  188.  
  189.  
  190.  
  191.  
  192. //
  193. // D_Display
  194. //  draw current display, possibly wiping it from the previous
  195. //
  196.  
  197. // wipegamestate can be set to -1 to force a wipe on the next draw
  198. gamestate_t     wipegamestate = GS_DEMOSCREEN;
  199. extern  boolean setsizeneeded;
  200. extern  int             showMessages;
  201. void R_ExecuteSetViewSize (void);
  202.  
  203. void D_Display (void)
  204. {
  205.     static  boolean             maponhustate = false;
  206.     static  boolean             viewactivestate = false;
  207.     static  boolean             menuactivestate = false;
  208.     static  boolean             inhelpscreensstate = false;
  209.     static  boolean             fullscreen = false;
  210.     static  gamestate_t         oldgamestate = -1;
  211.     static  int                 borderdrawcount;
  212.     int                         nowtime;
  213.     int                         tics;
  214.     int                         wipestart;
  215.     int                         y;
  216.     boolean                     done;
  217.     boolean                     wipe;
  218.     boolean                     redrawsbar;
  219.  
  220.     if (nodrawers)
  221.         return;                    // for comparative timing / profiling
  222.                 
  223.     redrawsbar = false;
  224.     
  225.     // change the view size if needed
  226.     if (setsizeneeded)
  227.     {
  228.         R_ExecuteSetViewSize ();
  229.         oldgamestate = -1;                      // force background redraw
  230.         borderdrawcount = 3;
  231.     }
  232.  
  233.     // force redraw border if we changed maponhu type
  234.     if (maponhu > 0 && maponhustate == 0)
  235.     {
  236.         oldgamestate = -1;                      // force background redraw
  237.         borderdrawcount = 3;
  238.     }
  239.  
  240.     // save the current screen if about to wipe
  241.     if (gamestate != wipegamestate)
  242.     {
  243.         wipe = true;
  244.         wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
  245.     }
  246.     else
  247.         wipe = false;
  248.  
  249.     // start updating gfx in screens[0] here
  250.     I_StartUpdate ();
  251.  
  252.     if (gamestate == GS_LEVEL && gametic)
  253.         HU_Erase();
  254.     
  255.     // do buffered drawing
  256.     switch (gamestate)
  257.     {
  258.       case GS_LEVEL:
  259.         if (!gametic)
  260.             break;
  261.         /* Map On Headup Patch - CDE - 97'
  262.         if (automapactive)
  263.             AM_Drawer ();
  264.         */
  265.         if (wipe || (viewheight != SCREENHEIGHT && fullscreen) )
  266.             redrawsbar = true;
  267.         if (inhelpscreensstate && !inhelpscreens)
  268.             redrawsbar = true;              // just put away the help screen
  269.         ST_Drawer (viewheight == SCREENHEIGHT, redrawsbar );
  270.         fullscreen = viewheight == SCREENHEIGHT;
  271.         break;
  272.  
  273.       case GS_INTERMISSION:
  274.         WI_Drawer ();
  275.         break;
  276.  
  277.       case GS_FINALE:
  278.         F_Drawer ();
  279.         break;
  280.  
  281.       case GS_DEMOSCREEN:
  282.         D_PageDrawer ();
  283.         break;
  284.     }
  285.     
  286.     // draw buffered stuff to screen
  287.     I_UpdateNoBlit ();
  288.     
  289.     // draw the view directly
  290.     if (gamestate == GS_LEVEL && (!automapactive || maponhu) && gametic)
  291.         R_RenderPlayerView (&players[displayplayer]);
  292.  
  293.     /* Map On HeadUp Patch - CDE 98' */
  294.     if (gamestate == GS_LEVEL && automapactive)
  295.         AM_Drawer ();
  296.  
  297.     if (gamestate == GS_LEVEL && gametic)
  298.         HU_Drawer ();
  299.     
  300.     // clean up border stuff
  301.     if (gamestate != oldgamestate && gamestate != GS_LEVEL)
  302.         I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE), 0);
  303.  
  304.     // see if the border needs to be initially drawn
  305.     if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
  306.     {
  307.         viewactivestate = false;        // view was not active
  308.         R_FillBackScreen ();    // draw the pattern into the back screen
  309.     }
  310.  
  311.     // see if the border needs to be updated to the screen
  312.     if (gamestate == GS_LEVEL && (maponhu || !automapactive) /* && scaledviewwidth != 320 */)
  313.     {
  314.         if (menuactive || menuactivestate || !viewactivestate)
  315.             borderdrawcount = 3;
  316.         if (borderdrawcount)
  317.         {
  318.             R_DrawViewBorder ();    // erase old menu stuff
  319.             borderdrawcount--;
  320.         }
  321.     }
  322.  
  323.     maponhustate = maponhu; // CDE'98
  324.     menuactivestate = menuactive;
  325.     viewactivestate = viewactive;
  326.     inhelpscreensstate = inhelpscreens;
  327.     oldgamestate = wipegamestate = gamestate;
  328.     
  329.     // draw pause pic
  330.     if (paused)
  331.     {
  332.         if (automapactive)
  333.             y = 4;
  334.         else
  335.             y = viewwindowy+4;
  336.         V_DrawPatchDirect(viewwindowx+(scaledviewwidth-68)/2,
  337.                           y,0,W_CacheLumpName ("M_PAUSE", PU_CACHE));
  338.     }
  339.  
  340.  
  341.     // menus go directly to the screen
  342.     M_Drawer ();          // menu is drawn even on top of everything
  343.     NetUpdate ();         // send out any new accumulation
  344.  
  345.  
  346.     // normal update
  347.     if (!wipe)
  348.     {
  349.         I_FinishUpdate ();              // page flip or blit buffer
  350.         return;
  351.     }
  352.     
  353.     // wipe update
  354.     wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
  355.  
  356.     wipestart = I_GetTime () - 1;
  357.  
  358.     do
  359.     {
  360.         do
  361.         {
  362.             nowtime = I_GetTime ();
  363.             tics = nowtime - wipestart;
  364.         } while (!tics);
  365.         wipestart = nowtime;
  366.         done = wipe_ScreenWipe(wipe_Melt
  367.                                , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics);
  368.         I_StartUpdate ();
  369.         I_UpdateNoBlit ();
  370.         M_Drawer ();                   // menu is drawn even on top of wipes
  371.         I_FinishUpdate ();             // page flip or blit buffer
  372.     } while (!done);
  373. }
  374.  
  375.  
  376.  
  377. //
  378. //  D_DoomLoop
  379. //
  380. extern  boolean         demorecording;
  381.  
  382. void D_DoomLoop (void)
  383. {
  384.     if (demorecording)
  385.         G_BeginRecording ();
  386.                 
  387.     if (M_CheckParm ("-debugfile"))
  388.     {
  389.         char    filename[20];
  390.         sprintf (filename,"debug%i.txt",consoleplayer);
  391.         printf ("debug output to: %s\n",filename);
  392.         debugfile = fopen (filename,"w");
  393.     }
  394.         
  395.     I_InitGraphics ();
  396.  
  397.     while (1)
  398.     {
  399.         // frame syncronous IO operations
  400.         I_StartFrame ();                
  401.         
  402.         // process one or more tics
  403.         if (singletics)
  404.         {
  405.             I_StartTic ();
  406.             D_ProcessEvents ();
  407.             G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
  408.             if (advancedemo)
  409.                 D_DoAdvanceDemo ();
  410.             M_Ticker ();
  411.             G_Ticker ();
  412.             gametic++;
  413.             maketic++;
  414.         }
  415.         else
  416.         {
  417.             TryRunTics (); // will run at least one tic
  418.         }
  419.                 
  420.         S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
  421.  
  422.         // Update display, next frame, with current state.
  423.         D_Display ();
  424.  
  425. #if 0
  426. #ifndef SNDSERV
  427.         // Sound mixing for the buffer is snychronous.
  428.         I_UpdateSound();
  429. #endif  
  430.         // Synchronous sound output is explicitly called.
  431. #ifndef SNDINTR
  432.         // Update sound output.
  433.         I_SubmitSound();
  434. #endif
  435. #endif
  436.     }
  437. }
  438.  
  439.  
  440.  
  441. //
  442. //  DEMO LOOP
  443. //
  444. int             demosequence;
  445. int             pagetic;
  446. char                    *pagename;
  447.  
  448.  
  449. //
  450. // D_PageTicker
  451. // Handles timing for warped projection
  452. //
  453. void D_PageTicker (void)
  454. {
  455.     if (--pagetic < 0)
  456.         D_AdvanceDemo ();
  457. }
  458.  
  459.  
  460.  
  461. //
  462. // D_PageDrawer
  463. //
  464. void D_PageDrawer (void)
  465. {
  466.     V_DrawPatchInDirect (0,0, 0, W_CacheLumpName(pagename, PU_CACHE));
  467. }
  468.  
  469.  
  470. //
  471. // D_AdvanceDemo
  472. // Called after each demo or intro demosequence finishes
  473. //
  474. void D_AdvanceDemo (void)
  475. {
  476.     advancedemo = true;
  477. }
  478.  
  479.  
  480. //
  481. // This cycles through the demo sequences.
  482. // FIXME - version dependend demo numbers?
  483. //
  484.  void D_DoAdvanceDemo (void)
  485. {
  486.     players[consoleplayer].playerstate = PST_LIVE;  // not reborn
  487.     advancedemo = false;
  488.     usergame = false;               // no save / end game here
  489.     paused = false;
  490.     gameaction = ga_nothing;
  491.  
  492.     if ( gamemode == retail )
  493.       demosequence = (demosequence+1)%7;
  494.     else
  495.       demosequence = (demosequence+1)%6;
  496.     
  497.     switch (demosequence)
  498.     {
  499.       case 0:
  500.         if ( gamemode == commercial )
  501.             pagetic = 35 * 11;
  502.         else
  503.             pagetic = 170;
  504.         gamestate = GS_DEMOSCREEN;
  505.         pagename = "TITLEPIC";
  506.         if ( gamemode == commercial )
  507.           S_StartMusic(mus_dm2ttl);
  508.         else
  509.           S_StartMusic (mus_intro);
  510.         break;
  511.       case 1:
  512.         G_DeferedPlayDemo ("demo1");
  513.         break;
  514.       case 2:
  515.         pagetic = 200;
  516.         gamestate = GS_DEMOSCREEN;
  517.         pagename = "CREDIT";
  518.         break;
  519.       case 3:
  520.         G_DeferedPlayDemo ("demo2");
  521.         break;
  522.       case 4:
  523.         gamestate = GS_DEMOSCREEN;
  524.         if ( gamemode == commercial)
  525.         {
  526.             pagetic = 35 * 11;
  527.             pagename = "TITLEPIC";
  528.             S_StartMusic(mus_dm2ttl);
  529.         }
  530.         else
  531.         {
  532.             pagetic = 200;
  533.  
  534.             if ( gamemode == retail )
  535.               pagename = "CREDIT";
  536.             else
  537.               pagename = "HELP2";
  538.         }
  539.         break;
  540.       case 5:
  541.         G_DeferedPlayDemo ("demo3");
  542.         break;
  543.         // THE DEFINITIVE DOOM Special Edition demo
  544.       case 6:
  545.         G_DeferedPlayDemo ("demo4");
  546.         break;
  547.     }
  548. }
  549.  
  550.  
  551.  
  552. //
  553. // D_StartTitle
  554. //
  555. void D_StartTitle (void)
  556. {
  557.     gameaction = ga_nothing;
  558.     demosequence = -1;
  559.     D_AdvanceDemo ();
  560. }
  561.  
  562.  
  563.  
  564.  
  565. //      print title for every printed line
  566. char            title[128];
  567.  
  568.  
  569.  
  570. //
  571. // D_AddFile
  572. //
  573. void D_AddFile (char *file)
  574. {
  575.     int     numwadfiles;
  576.     char    *newfile;
  577.         
  578.     for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++)
  579.         ;
  580.  
  581.     newfile = malloc (strlen(file)+1);
  582.     strcpy (newfile, file);
  583.         
  584.     wadfiles[numwadfiles] = newfile;
  585. }
  586.  
  587.  
  588. #ifdef DEBUGGING
  589. #define DIRSTRING ""
  590. #else
  591. #define DIRSTRING "PROGDIR:"
  592. #endif
  593.  
  594. //
  595. // IdentifyVersion
  596. // Checks availability of IWAD files by name,
  597. // to determine whether registered/commercial features
  598. // should be executed (notably loading PWAD's).
  599. //
  600. void IdentifyVersion (void)
  601. {
  602.     int         p;
  603.  
  604.     char*       doom1wad;
  605.     char*       doomwad;
  606.     char*       doomuwad;
  607.     char*       doom2wad;
  608.  
  609.     char*       doom2fwad;
  610.     char*       plutoniawad;
  611.     char*       tntwad;
  612.  
  613. #ifdef NORMALUNIX
  614.     static char home[256];
  615.     static char doomwaddir[256];
  616.  
  617.     if (getenv ("DOOMWADDIR") != NULL) {
  618.       strcpy (doomwaddir, getenv("DOOMWADDIR"));
  619.       if (doomwaddir[strlen(doomwaddir)-1] != '/' && doomwaddir[strlen(doomwaddir)-1] != ':')
  620.         strcat (doomwaddir, "/");
  621.     } else {
  622.       strcpy (doomwaddir, DIRSTRING);
  623.       p = M_CheckParm ("-waddir");
  624.       if (p) {
  625.         strcpy(doomwaddir, myargv[p+1]);
  626.         if (doomwaddir[strlen(doomwaddir)-1] != '/' && doomwaddir[strlen(doomwaddir)-1] != ':')
  627.           strcat (doomwaddir, "/");
  628.       }
  629.     }
  630.  
  631.     // Commercial.
  632.     doom2wad = malloc(strlen(doomwaddir)+1+9+1);
  633.     sprintf(doom2wad, "%sdoom2.wad", doomwaddir);
  634.  
  635.     // Retail.
  636.     doomuwad = malloc(strlen(doomwaddir)+1+8+1);
  637.     sprintf(doomuwad, "%sdoomu.wad", doomwaddir);
  638.     
  639.     // Registered.
  640.     doomwad = malloc(strlen(doomwaddir)+1+8+1);
  641.     sprintf(doomwad, "%sdoom.wad", doomwaddir);
  642.     
  643.     // Shareware.
  644.     doom1wad = malloc(strlen(doomwaddir)+1+9+1);
  645.     sprintf(doom1wad, "%sdoom1.wad", doomwaddir);
  646.  
  647.      // Bug, dear Shawn.
  648.     // Insufficient malloc, caused spurious realloc errors.
  649.     plutoniawad = malloc(strlen(doomwaddir)+1+/*9*/12+1);
  650.     sprintf(plutoniawad, "%splutonia.wad", doomwaddir);
  651.  
  652.     tntwad = malloc(strlen(doomwaddir)+1+9+1);
  653.     sprintf(tntwad, "%stnt.wad", doomwaddir);
  654.  
  655.  
  656.     // French stuff.
  657.     doom2fwad = malloc(strlen(doomwaddir)+1+10+1);
  658.     sprintf(doom2fwad, "%sdoom2f.wad", doomwaddir);
  659.  
  660. #ifdef AMIGA
  661.     if (getenv ("HOME") != NULL) {
  662.       strcpy (home, getenv("HOME"));
  663.       if (home[strlen(home)-1] != '/' && home[strlen(home)-1] != ':')
  664.         strcat (home, "/");
  665.     } else
  666.       home[0] = '\0';
  667. #else
  668.     home = getenv ("HOME");
  669.     if (!home)
  670.       I_Error("Please set $HOME to your home directory");
  671. #endif
  672.     sprintf(basedefault, "%s.doomrc", home);
  673. #endif
  674.  
  675.     if (M_CheckParm ("-shdev"))
  676.     {
  677.         gamemode = shareware;
  678.         devparm = true;
  679.         D_AddFile (DEVDATA"doom1.wad");
  680.         D_AddFile (DEVMAPS"data_se/texture1.lmp");
  681.         D_AddFile (DEVMAPS"data_se/pnames.lmp");
  682.         strcpy (basedefault,DEVDATA"default.cfg");
  683.         return;
  684.     }
  685.  
  686.     if (M_CheckParm ("-regdev"))
  687.     {
  688.         gamemode = registered;
  689.         devparm = true;
  690.         D_AddFile (DEVDATA"doom.wad");
  691.         D_AddFile (DEVMAPS"data_se/texture1.lmp");
  692.         D_AddFile (DEVMAPS"data_se/texture2.lmp");
  693.         D_AddFile (DEVMAPS"data_se/pnames.lmp");
  694.         strcpy (basedefault,DEVDATA"default.cfg");
  695.         return;
  696.     }
  697.  
  698.     if (M_CheckParm ("-comdev"))
  699.     {
  700.         gamemode = commercial;
  701.         devparm = true;
  702.         /* I don't bother
  703.         if(plutonia)
  704.             D_AddFile (DEVDATA"plutonia.wad");
  705.         else if(tnt)
  706.             D_AddFile (DEVDATA"tnt.wad");
  707.         else*/
  708.             D_AddFile (DEVDATA"doom2.wad");
  709.             
  710.         D_AddFile (DEVMAPS"cdata/texture1.lmp");
  711.         D_AddFile (DEVMAPS"cdata/pnames.lmp");
  712.         strcpy (basedefault,DEVDATA"default.cfg");
  713.         return;
  714.     }
  715.  
  716.     if ( !access (doom2fwad,R_OK) )
  717.     {
  718.         gamemode = commercial;
  719.         // C'est ridicule!
  720.         // Let's handle languages in config files, okay?
  721.         language = french;
  722.         printf("French version\n");
  723.         D_AddFile (doom2fwad);
  724.         return;
  725.     }
  726.  
  727.     if ( !access (doom2wad,R_OK) )
  728.     {
  729.         gamemode = commercial;
  730.         D_AddFile (doom2wad);
  731.         return;
  732.     }
  733.  
  734.     if ( !access (plutoniawad, R_OK ) )
  735.     {
  736.       gamemode = commercial;
  737.       D_AddFile (plutoniawad);
  738.       return;
  739.     }
  740.  
  741.     if ( !access ( tntwad, R_OK ) )
  742.     {
  743.       gamemode = commercial;
  744.       D_AddFile (tntwad);
  745.       return;
  746.     }
  747.  
  748.     if ( !access (doomuwad,R_OK) )
  749.     {
  750.       gamemode = retail;
  751.       D_AddFile (doomuwad);
  752.       return;
  753.     }
  754.  
  755.     if ( !access (doomwad,R_OK) )
  756.     {
  757.       gamemode = registered;
  758.       D_AddFile (doomwad);
  759.       return;
  760.     }
  761.  
  762.     if ( !access (doom1wad,R_OK) )
  763.     {
  764.       gamemode = shareware;
  765.       D_AddFile (doom1wad);
  766.       return;
  767.     }
  768.  
  769.     printf("Game mode indeterminate.\n");
  770.     gamemode = indetermined;
  771.  
  772.     // We don't abort. Let's see what the PWAD contains.
  773.     //exit(1);
  774.     //I_Error ("Game mode indeterminate\n");
  775. }
  776.  
  777. //
  778. // Find a Response File
  779. //
  780. void FindResponseFile (void)
  781. {
  782.     int             i;
  783.         
  784.     for (i = 1;i < myargc;i++)
  785.         if (myargv[i][0] == '@')
  786.         {
  787.             FILE *          handle;
  788.             int             size;
  789.             int             k;
  790.             int             index;
  791.             int             indexinfile;
  792.             char    *infile;
  793.             char    *file;
  794.             char    *moreargs[20];
  795.             char    *firstargv;
  796.                         
  797.             // READ THE RESPONSE FILE INTO MEMORY
  798.             handle = fopen (&myargv[i][1],"rb");
  799.             if (!handle)
  800.             {
  801.                 printf ("\nNo such response file!");
  802.                 exit(1);
  803.             }
  804.             printf("Found response file %s!\n",&myargv[i][1]);
  805.             fseek (handle,0,SEEK_END);
  806.             size = ftell(handle);
  807.             fseek (handle,0,SEEK_SET);
  808.             file = malloc (size);
  809.             fread (file,size,1,handle);
  810.             fclose (handle);
  811.                         
  812.             // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
  813.             for (index = 0,k = i+1; k < myargc; k++)
  814.                 moreargs[index++] = myargv[k];
  815.                         
  816.             firstargv = myargv[0];
  817.             myargv = malloc(sizeof(char *)*MAXARGVS);
  818.             memset(myargv,0,sizeof(char *)*MAXARGVS);
  819.             myargv[0] = firstargv;
  820.                         
  821.             infile = file;
  822.             indexinfile = k = 0;
  823.             indexinfile++;  // SKIP PAST ARGV[0] (KEEP IT)
  824.             do
  825.             {
  826.                 myargv[indexinfile++] = infile+k;
  827.                 while(k < size &&
  828.                       ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
  829.                     k++;
  830.                 *(infile+k) = 0;
  831.                 while(k < size &&
  832.                       ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
  833.                     k++;
  834.             } while(k < size);
  835.                         
  836.             for (k = 0;k < index;k++)
  837.                 myargv[indexinfile++] = moreargs[k];
  838.             myargc = indexinfile;
  839.         
  840.             // DISPLAY ARGS
  841.             printf("%d command-line args:\n",myargc);
  842.             for (k=1;k<myargc;k++)
  843.                 printf("%s\n",myargv[k]);
  844.  
  845.             break;
  846.         }
  847. }
  848.  
  849.  
  850. //
  851. // D_DoomMain
  852. //
  853. void D_DoomMain (void)
  854. {
  855.     int             p;
  856.     char            file[256];
  857.  
  858.     FindResponseFile ();
  859.         
  860.     IdentifyVersion ();
  861.  
  862. #ifndef __VBCC__
  863.     setbuf (stdout, NULL);
  864. #endif
  865.  
  866.     modifiedgame = false;
  867.         
  868.     nomonsters = M_CheckParm ("-nomonsters");
  869.     respawnparm = M_CheckParm ("-respawn");
  870.     fastparm = M_CheckParm ("-fast");
  871.     rotatemap = M_CheckParm ("-rotatemap");
  872.     devparm = M_CheckParm ("-devparm");
  873.     maponhu = (M_CheckParm ("-maponhu") != 0);
  874.  
  875.     if (M_CheckParm ("-altdeath"))
  876.         deathmatch = 2;
  877.     else if (M_CheckParm ("-deathmatch"))
  878.         deathmatch = 1;
  879.  
  880.     switch ( gamemode )
  881.     {
  882.       case retail:
  883.         sprintf (title,
  884.                  "                         "
  885.                  "The Ultimate DOOM Startup v%i.%i"
  886.                  "                           ",
  887.                  VERSION/100,VERSION%100);
  888.         break;
  889.       case shareware:
  890.         sprintf (title,
  891.                  "                            "
  892.                  "DOOM Shareware Startup v%i.%i"
  893.                  "                           ",
  894.                  VERSION/100,VERSION%100);
  895.         break;
  896.       case registered:
  897.         sprintf (title,
  898.                  "                            "
  899.                  "DOOM Registered Startup v%i.%i"
  900.                  "                           ",
  901.                  VERSION/100,VERSION%100);
  902.         break;
  903.       case commercial:
  904.         sprintf (title,
  905.                  "                         "
  906.                  "DOOM 2: Hell on Earth v%i.%i"
  907.                  "                           ",
  908.                  VERSION/100,VERSION%100);
  909.         break;
  910. /*FIXME
  911.        case pack_plut:
  912.         sprintf (title,
  913.                  "                   "
  914.                  "DOOM 2: Plutonia Experiment v%i.%i"
  915.                  "                           ",
  916.                  VERSION/100,VERSION%100);
  917.         break;
  918.       case pack_tnt:
  919.         sprintf (title,
  920.                  "                     "
  921.                  "DOOM 2: TNT - Evilution v%i.%i"
  922.                  "                           ",
  923.                  VERSION/100,VERSION%100);
  924.         break;
  925. */
  926.       default:
  927.         sprintf (title,
  928.                  "                     "
  929.                  "Public DOOM - v%i.%i"
  930.                  "                           ",
  931.                  VERSION/100,VERSION%100);
  932.         break;
  933.     }
  934.     
  935.     printf ("%s\n",title);
  936.  
  937.     if (devparm)
  938.         printf(D_DEVSTR);
  939.     
  940.     if (M_CheckParm("-cdrom"))
  941.     {
  942.         printf(D_CDROM);
  943. #if !defined(__GNUC__) && !defined(__VBCC__)
  944. #ifdef __SASC
  945.         mkdir("c:\\doomdata");
  946. #else
  947.         mkdir("c:\\doomdata",0);
  948. #endif
  949. #endif
  950.         strcpy (basedefault,"c:/doomdata/default.cfg");
  951.     }   
  952.     
  953.     // turbo option
  954.     if ( (p=M_CheckParm ("-turbo")) )
  955.     {
  956.         int     scale = 200;
  957.         extern int forwardmove[2];
  958.         extern int sidemove[2];
  959.         
  960.         if (p<myargc-1)
  961.             scale = atoi (myargv[p+1]);
  962.         if (scale < 10)
  963.             scale = 10;
  964.         if (scale > 400)
  965.             scale = 400;
  966.         printf ("turbo scale: %i%%\n",scale);
  967.         forwardmove[0] = forwardmove[0]*scale/100;
  968.         forwardmove[1] = forwardmove[1]*scale/100;
  969.         sidemove[0] = sidemove[0]*scale/100;
  970.         sidemove[1] = sidemove[1]*scale/100;
  971.     }
  972.     
  973.     // add any files specified on the command line with -file wadfile
  974.     // to the wad list
  975.     //
  976.     // convenience hack to allow -wart e m to add a wad file
  977.     // prepend a tilde to the filename so wadfile will be reloadable
  978.     p = M_CheckParm ("-wart");
  979.     if (p)
  980.     {
  981.         myargv[p][4] = 'p';     // big hack, change to -warp
  982.  
  983.         // Map name handling.
  984.         switch (gamemode )
  985.         {
  986.           case shareware:
  987.           case retail:
  988.           case registered:
  989.             sprintf (file,"~"DEVMAPS"E%cM%c.wad",
  990.                      myargv[p+1][0], myargv[p+2][0]);
  991.             printf("Warping to Episode %s, Map %s.\n",
  992.                    myargv[p+1],myargv[p+2]);
  993.             break;
  994.             
  995.           case commercial:
  996.           default:
  997.             p = atoi (myargv[p+1]);
  998.             if (p<10)
  999.               sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p);
  1000.             else
  1001.               sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p);
  1002.             break;
  1003.         }
  1004.         D_AddFile (file);
  1005.     }
  1006.         
  1007.     p = M_CheckParm ("-file");
  1008.     if (p)
  1009.     {
  1010.         // the parms after p are wadfile/lump names,
  1011.         // until end of parms or another - preceded parm
  1012.         modifiedgame = true;            // homebrew levels
  1013.         while (++p != myargc && myargv[p][0] != '-')
  1014.             D_AddFile (myargv[p]);
  1015.     }
  1016.  
  1017.     /* DeHacked Patch !! */
  1018.     p = M_CheckParm ("-deh");
  1019.     if (p)
  1020.     {
  1021.         // the parms after p are wadfile/lump names,
  1022.         // until end of parms or another - preceded parm
  1023.         //modifiedgame = true;            // homebrew levels
  1024.         while (++p != myargc && myargv[p][0] != '-')
  1025.             DE_AddDeh(myargv[p]);
  1026.     }
  1027.  
  1028.     p = M_CheckParm ("-playdemo");
  1029.  
  1030.     if (!p)
  1031.         p = M_CheckParm ("-timedemo");
  1032.  
  1033.     if (p && p < myargc-1)
  1034.     {
  1035.         sprintf (file,"%s.lmp", myargv[p+1]);
  1036.         D_AddFile (file);
  1037.         printf("Playing demo %s.lmp.\n",myargv[p+1]);
  1038.     }
  1039.     
  1040.     // get skill / episode / map from parms
  1041.     startskill = sk_medium;
  1042.     startepisode = 1;
  1043.     startmap = 1;
  1044.     autostart = false;
  1045.  
  1046.                 
  1047.     p = M_CheckParm ("-skill");
  1048.     if (p && p < myargc-1)
  1049.     {
  1050.         startskill = myargv[p+1][0]-'1';
  1051.         autostart = true;
  1052.     }
  1053.  
  1054.     p = M_CheckParm ("-episode");
  1055.     if (p && p < myargc-1)
  1056.     {
  1057.         startepisode = myargv[p+1][0]-'0';
  1058.         startmap = 1;
  1059.         autostart = true;
  1060.     }
  1061.         
  1062.     p = M_CheckParm ("-timer");
  1063.     if (p && p < myargc-1 && deathmatch)
  1064.     {
  1065.         int     time;
  1066.         time = atoi(myargv[p+1]);
  1067.         printf("Levels will end after %d minute",time);
  1068.         if (time>1)
  1069.             printf("s");
  1070.         printf(".\n");
  1071.     }
  1072.  
  1073.     p = M_CheckParm ("-avg");
  1074.     if (p && p < myargc-1 && deathmatch)
  1075.         printf("Austin Virtual Gaming: Levels will end after 20 minutes\n");
  1076.  
  1077.     p = M_CheckParm ("-warp");
  1078.     if (p && p < myargc-1)
  1079.     {
  1080.         if (gamemode == commercial)
  1081.             startmap = atoi (myargv[p+1]);
  1082.         else
  1083.         {
  1084.             startepisode = myargv[p+1][0]-'0';
  1085.             startmap = myargv[p+2][0]-'0';
  1086.         }
  1087.         autostart = true;
  1088.     }
  1089.     
  1090.     // init subsystems
  1091.     printf ("V_Init: allocate screens.\n");
  1092.     V_Init ();
  1093.  
  1094.     printf ("M_LoadDefaults: Load system defaults.\n");
  1095.     M_LoadDefaults ();              // load before initing other systems
  1096.  
  1097.     printf ("Z_Init: Init zone memory allocation daemon. \n");
  1098.     Z_Init ();
  1099.  
  1100.     printf ("W_Init: Init WADfiles.\n");
  1101.     W_InitMultipleFiles (wadfiles);
  1102.     
  1103.  
  1104.     // Check for -file in shareware
  1105.     if (modifiedgame)
  1106.     {
  1107.         // These are the lumps that will be checked in IWAD,
  1108.         // if any one is not present, execution will be aborted.
  1109.         char name[23][8]=
  1110.         {
  1111.             "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
  1112.             "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
  1113.             "dphoof","bfgga0","heada1","cybra1","spida1d1"
  1114.         };
  1115.         int i;
  1116.         
  1117.         if ( gamemode == shareware)
  1118.             I_Error("\nYou cannot -file with the shareware "
  1119.                     "version. Register!");
  1120.  
  1121.         // Check for fake IWAD with right name,
  1122.         // but w/o all the lumps of the registered version. 
  1123.         if (gamemode == registered)
  1124.             for (i = 0;i < 23; i++)
  1125.                 if (W_CheckNumForName(name[i])<0)
  1126.                     I_Error("\nThis is not the registered version.");
  1127.     }
  1128.     
  1129.     // Iff additonal PWAD files are used, print modified banner
  1130.     if (modifiedgame)
  1131.     {
  1132.         /*m*/printf (
  1133.             "===========================================================================\n"
  1134.             "ATTENTION:  This version of DOOM has been modified.  If you would like to\n"
  1135.             "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n"
  1136.             "        You will not receive technical support for modified games.\n"
  1137.             "                      press enter to continue\n"
  1138.             "===========================================================================\n"
  1139.             );
  1140.         getchar ();
  1141.     }
  1142.         
  1143.  
  1144.     // Check and print which version is executed.
  1145.     switch ( gamemode )
  1146.     {
  1147.       case shareware:
  1148.       case indetermined:
  1149.         printf (
  1150.             "===========================================================================\n"
  1151.             "                                Shareware!\n"
  1152.             "===========================================================================\n"
  1153.         );
  1154.         break;
  1155.       case registered:
  1156.       case retail:
  1157.       case commercial:
  1158.         printf (
  1159.             "===========================================================================\n"
  1160.             "                 Commercial product - do not distribute!\n"
  1161.             "         Please report software piracy to the SPA: 1-800-388-PIR8\n"
  1162.             "===========================================================================\n"
  1163.         );
  1164.         break;
  1165.         
  1166.       default:
  1167.         // Ouch.
  1168.         break;
  1169.     }
  1170.  
  1171.     printf ("M_Init: Init miscellaneous info.\n");
  1172.     M_Init ();
  1173.  
  1174.     printf ("R_Init: Init DOOM refresh daemon - ");
  1175.     R_Init ();
  1176.  
  1177.     printf ("\nP_Init: Init Playloop state.\n");
  1178.     P_Init ();
  1179.  
  1180.     printf ("I_Init: Setting up machine state.\n");
  1181.     I_Init ();
  1182.  
  1183.     printf ("D_CheckNetGame: Checking network game status.\n");
  1184.     D_CheckNetGame ();
  1185.  
  1186.     printf ("S_Init: Setting up sound.\n");
  1187.     S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
  1188.  
  1189.     printf ("HU_Init: Setting up heads up display.\n");
  1190.     HU_Init ();
  1191.  
  1192.     printf ("ST_Init: Init status bar.\n");
  1193.     ST_Init ();
  1194.  
  1195.     // check for a driver that wants intermission stats
  1196.     p = M_CheckParm ("-statcopy");
  1197.     if (p && p<myargc-1)
  1198.     {
  1199.         // for statistics driver
  1200.         extern  void*   statcopy;                            
  1201.  
  1202.         statcopy = (void*)atoi(myargv[p+1]);
  1203.         printf ("External statistics registered.\n");
  1204.     }
  1205.     
  1206.     // start the apropriate game based on parms
  1207.     p = M_CheckParm ("-record");
  1208.  
  1209.     if (p && p < myargc-1)
  1210.     {
  1211.         G_RecordDemo (myargv[p+1]);
  1212.         autostart = true;
  1213.     }
  1214.         
  1215.     p = M_CheckParm ("-playdemo");
  1216.     if (p && p < myargc-1)
  1217.     {
  1218.         singledemo = true;              // quit after one demo
  1219.         G_DeferedPlayDemo (myargv[p+1]);
  1220.         D_DoomLoop ();  // never returns
  1221.     }
  1222.         
  1223.     p = M_CheckParm ("-timedemo");
  1224.     if (p && p < myargc-1)
  1225.     {
  1226.         G_TimeDemo (myargv[p+1]);
  1227.         D_DoomLoop ();  // never returns
  1228.     }
  1229.         
  1230.     p = M_CheckParm ("-loadgame");
  1231.     if (p && p < myargc-1)
  1232.     {
  1233.         if (M_CheckParm("-cdrom"))
  1234.             sprintf(file, "c:\\doomdata\\"SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
  1235.         else
  1236.             sprintf(file, SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
  1237.         G_LoadGame (file);
  1238.     }
  1239.         
  1240.  
  1241.     if ( gameaction != ga_loadgame )
  1242.     {
  1243.         if (autostart || netgame)
  1244.             G_InitNew (startskill, startepisode, startmap);
  1245.         else
  1246.             D_StartTitle ();                // start up intro loop
  1247.  
  1248.     }
  1249.  
  1250.     D_DoomLoop ();  // never returns
  1251. }
  1252.